/*
 * This file is part of connotea-java.
 *
 * connotea-java is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * connotea-java is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package org.connotea;

import static org.apache.commons.lang.builder.ToStringBuilder.reflectionToString;

import java.io.Serializable;

import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.restlet.data.Reference;

/**
 * Message entity bean.
 * 
 * @author <a href="mailto:christopher.townson@googlemail.com">Christopher
 *         Townson</a>
 */
public class Message implements Comparable<Message>, Serializable {

    /**
     * A connotea-java application message appropriate to the case where we get
     * an unparseable message as the result of an API call where a parseable
     * message is expected.
     */
    public static final Message INVALID = new Message(-2,
            "invalid representation", false);

    /**
     * A connotea-java application message appropriate to the case where we get
     * nothing as the result of an API call when a message is expected.
     */
    public static final Message NULL = new Message(-1, "null message", false);

    /**
     * A connotea-java application message appropriate to the case where we
     * cannot complete a (POST) request due to form encoding failure.
     */
    public static final Message UNENCODEABLE_FORM = new Message(-3,
            "unencodeable form", false);

    private static final long serialVersionUID = 1L;

    private String apiVersion;

    private String bibliotechVersion;

    private int code;

    private Reference location;

    private String message;

    private boolean success;

    private String user;

    /**
     * Default, no-argument constructor.
     */
    public Message() {
        // do nothing
    }

    /**
     * Create a Message using the supplied field values.
     * 
     * @param code the code
     * @param message the message
     * @param success the success
     */
    public Message(int code, String message, boolean success) {
        setCode(code);
        setMessage(message);
        setSuccess(success);
    }

    /**
     * Comparability is based on code, success, message, location, user,
     * apiVersion, then bibliotechVersion.
     * 
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    public int compareTo(Message message) {
        return new CompareToBuilder().append(code, message.code).append(
                success, message.success).append(this.message, message.message)
                .append(location, message.location).append(user, message.user)
                .append(apiVersion, message.apiVersion).append(
                        bibliotechVersion, message.bibliotechVersion)
                .toComparison();
    }

    /**
     * Equality is based on code, success, message, location, user, apiVersion,
     * then bibliotechVersion.
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Message)) {
            return false;
        }
        Message message = (Message) obj;
        return new EqualsBuilder().append(code, message.code).append(success,
                message.success).append(this.message, message.message).append(
                location, message.location).append(user, message.user).append(
                apiVersion, message.apiVersion).append(bibliotechVersion,
                message.bibliotechVersion).isEquals();
    }

    /**
     * Returns the apiVersion. This is the Connotea API version number.
     * 
     * @return the apiVersion
     */
    public String getApiVersion() {
        return apiVersion;
    }

    /**
     * Returns the bibliotechVersion. This is the Bibliotech version number.
     * 
     * @return the bibliotechVersion
     */
    public String getBibliotechVersion() {
        return bibliotechVersion;
    }

    /**
     * Returns the code. This is the HTTP status code returned by Connotea.
     * 
     * @return the code
     */
    public int getCode() {
        return code;
    }

    /**
     * Returns the location. This is the HTTP location header returned by
     * Connotea as part of the RDF response on certain API calls.
     * 
     * @return the location
     */
    public Reference getLocation() {
        return location;
    }

    /**
     * Returns the message. This is the error message returned by Connotea.
     * 
     * @return the message
     */
    public String getMessage() {
        return message;
    }

    /**
     * Returns the user. This is the username of the user making the request.
     * 
     * @return the user
     */
    public String getUser() {
        return user;
    }

    /**
     * HashCode is based on code, success, message, location, user, apiVersion,
     * then bibliotechVersion.
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(code).append(success).append(
                message).append(location).append(user).append(apiVersion)
                .append(bibliotechVersion).toHashCode();
    }

    /**
     * Returns the success. This is the "isFailure" (false) or "isSuccess"
     * (true) status returned as part of the RDF response by Connotea.
     * 
     * @return the success
     */
    public boolean isSuccess() {
        return success;
    }

    /**
     * Sets the apiVersion.
     * 
     * @param apiVersion the apiVersion to set
     */
    public void setApiVersion(String apiVersion) {
        this.apiVersion = apiVersion;
    }

    /**
     * Sets the bibliotechVersion.
     * 
     * @param bibliotechVersion the bibliotechVersion to set
     */
    public void setBibliotechVersion(String bibliotechVersion) {
        this.bibliotechVersion = bibliotechVersion;
    }

    /**
     * Sets the code.
     * 
     * @param code the code to set
     */
    public void setCode(int code) {
        this.code = code;
    }

    /**
     * Sets the location.
     * 
     * @param location the location to set
     */
    public void setLocation(Reference location) {
        this.location = location;
    }

    /**
     * Sets the message.
     * 
     * @param message the message to set
     */
    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * Sets the success.
     * 
     * @param success the success to set
     */
    public void setSuccess(boolean success) {
        this.success = success;
    }

    /**
     * Sets the user.
     * 
     * @param user the user to set
     */
    public void setUser(String user) {
        this.user = user;
    }

    /**
     * Pretty-prints the current object state.
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return reflectionToString(this);
    }
}
